{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "key_intro_md"
      },
      "source": [
        "# Key"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "key_desc_md"
      },
      "source": [
        "A `Key` in GTSAM is simply a `typedef` for `std::uint64_t`. It serves as a unique identifier for variables within a factor graph or values within a `Values` container. While you can use raw integer keys, GTSAM provides helper classes like `Symbol` and `LabeledSymbol` to create semantically meaningful keys that encode type and index information within the 64-bit integer."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "key_colab_md"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/borglab/gtsam/blob/develop/gtsam/inference/doc/Key.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "key_pip_code",
        "tags": [
          "remove-cell"
        ]
      },
      "outputs": [],
      "source": [
        "%pip install --quiet gtsam-develop"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "id": "key_import_code"
      },
      "outputs": [],
      "source": [
        "import gtsam\n",
        "from gtsam import Symbol, LabeledSymbol\n",
        "import numpy as np"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "key_usage_md"
      },
      "source": [
        "## Basic Usage\n",
        "\n",
        "Keys are typically created using `Symbol` or `LabeledSymbol` and then implicitly or explicitly cast to the `Key` type (integer)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "key_create_code",
        "outputId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Symbol Key (x0): 8646911284551352320\n",
            "Type: <class 'int'>\n",
            "LabeledSymbol Key (aB1): 7008163970141913089\n",
            "Type: <class 'int'>\n",
            "Plain Integer Key: 12345\n",
            "Type: <class 'int'>\n"
          ]
        }
      ],
      "source": [
        "sym = Symbol('x', 0)\n",
        "key_from_symbol = sym.key() # Or just 'sym' where a Key is expected\n",
        "print(f\"Symbol Key (x0): {key_from_symbol}\")\n",
        "print(f\"Type: {type(key_from_symbol)}\")\n",
        "\n",
        "lsym = LabeledSymbol(ord('a'), ord('B'), 1)\n",
        "key_from_labeled_symbol = lsym.key()\n",
        "print(f\"LabeledSymbol Key (aB1): {key_from_labeled_symbol}\")\n",
        "print(f\"Type: {type(key_from_labeled_symbol)}\")\n",
        "\n",
        "# You can also use plain integers, but it's less descriptive\n",
        "plain_key = 12345\n",
        "print(f\"Plain Integer Key: {plain_key}\")\n",
        "print(f\"Type: {type(plain_key)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "key_formatter_md"
      },
      "source": [
        "## Key Formatting\n",
        "\n",
        "When printing GTSAM objects that contain keys (like Factor Graphs or Values), you can specify a `KeyFormatter` to control how keys are displayed. The default formatter tries to interpret keys as `Symbol`s."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "key_format_code",
        "outputId": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Default Formatter:\n",
            "  Symbol Key: x0\n",
            "  LabeledSymbol Key: a18577348\n",
            "  Plain Key: 12345\n",
            "Custom Formatter:\n",
            "  Symbol Key: KEY[x0]\n",
            "  LabeledSymbol Key: KEY[a18577348]\n",
            "  Plain Key: KEY[12345]\n"
          ]
        }
      ],
      "source": [
        "print(\"Default Formatter:\")\n",
        "print(f\"  Symbol Key: {gtsam.DefaultKeyFormatter(key_from_symbol)}\")\n",
        "print(f\"  LabeledSymbol Key: {gtsam.DefaultKeyFormatter(key_from_labeled_symbol)}\")\n",
        "print(f\"  Plain Key: {gtsam.DefaultKeyFormatter(plain_key)}\")\n",
        "\n",
        "# Example of a custom formatter\n",
        "def my_formatter(key):\n",
        "    # Try interpreting as LabeledSymbol, then Symbol, then default\n",
        "    try:\n",
        "        lsym = gtsam.LabeledSymbol(key)\n",
        "        if lsym.label() != 0: # Check if it's likely a valid LabeledSymbol\n",
        "             return f\"KEY[{lsym.string()}]\"\n",
        "    except:\n",
        "        pass\n",
        "    try:\n",
        "        sym = gtsam.Symbol(key)\n",
        "        if sym.chr() != 0: # Check if it's likely a valid Symbol\n",
        "            return f\"KEY[{sym.string()}]\"\n",
        "    except:\n",
        "        pass\n",
        "    return f\"KEY[{key}]\"\n",
        "\n",
        "print(\"Custom Formatter:\")\n",
        "print(f\"  Symbol Key: {my_formatter(key_from_symbol)}\")\n",
        "print(f\"  LabeledSymbol Key: {my_formatter(key_from_labeled_symbol)}\")\n",
        "print(f\"  Plain Key: {my_formatter(plain_key)}\")\n",
        "\n",
        "# KeyVectors, KeyLists, KeySets can also be printed using formatters\n",
        "key_vector = gtsam.KeyVector([key_from_symbol, key_from_labeled_symbol, plain_key])\n",
        "# key_vector.print(\"My Vector: \", my_formatter) # .print() method uses formatter directly"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "gtsam",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.13.1"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
